package com.zhuanzhuan.hero.user.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.dto.SavePaymentDTO;
import com.zhuanzhuan.hero.user.entity.HeroUserPaymentInfo;
import com.zhuanzhuan.hero.user.enums.ExceptionMsgEnum;
import com.zhuanzhuan.hero.user.enums.PaymentTypeEnum;
import com.zhuanzhuan.hero.user.enums.StateEnum;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.mapper.HeroUserPaymentInfoMapper;
import com.zhuanzhuan.hero.user.service.HeroUserPaymentService;
import com.zhuanzhuan.hero.user.util.Assert;
import com.zhuanzhuan.hero.user.vo.UserPaymentVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ClassName UserPaymentServiceImpl
 * @Description
 * @Author hanjunjun
 * @Date 2024/6/21 16:03
 */
@Slf4j
@Service
public class HeroUserPaymentServiceImpl extends ServiceImpl<HeroUserPaymentInfoMapper, HeroUserPaymentInfo>
    implements HeroUserPaymentService {

    @Resource
    private HeroUserPaymentInfoMapper userPaymentInfoMapper;

    @Override
    public List<UserPaymentVO> queryUserPaymentInfoByUid(Long uid) {
        List<HeroUserPaymentInfo> records = this.listByUid(uid);
        //无论是否为空都需要组装数据返回给前端
        List<UserPaymentVO> voList = records.stream().map(this::convertUserPaymentVO).collect(Collectors.toList());
        //按照微信、支付宝、银行卡的顺序
        List<Integer> paymentTypeList = Arrays.asList(PaymentTypeEnum.WECHAT.getCode(), PaymentTypeEnum.ALI_PAY.getCode(),
            PaymentTypeEnum.BANK_CARD.getCode());
        List<UserPaymentVO> resultList = new ArrayList<>();
        paymentTypeList.forEach(paymentType -> {
            UserPaymentVO userPaymentVO =
                voList.stream().filter(vo -> paymentType.equals(vo.getPaymentType())).findFirst().orElse(null);
            if (Objects.nonNull(userPaymentVO)) {
                resultList.add(userPaymentVO);
            } else {
                resultList.add(new UserPaymentVO(paymentType));
            }
        });
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateUserPayment(Long uid, SavePaymentDTO savePaymentDTO) {
        boolean isDefaultType = NumConsts.ONE.equals(savePaymentDTO.getIsDefaultType());
        Integer paymentType = savePaymentDTO.getPaymentType();
        List<HeroUserPaymentInfo> paymentInfos = this.listByUid(uid);
        HeroUserPaymentInfo paymentInfo = paymentInfos.stream()
            .filter(record -> record.getPaymentType().equals(paymentType))
            .findFirst()
            .orElse(null);

        if (Objects.isNull(paymentInfo)) {
            log.info("还没有维护联系方式,type={}", paymentType);
            //如果一个收款方式都没有，把该方式强制设为默认收款方式
            if (CollectionUtils.isEmpty(paymentInfos)) {
                savePaymentDTO.setIsDefaultType(NumConsts.ONE);
            }
            this.saveUserPayment(uid, savePaymentDTO);
        } else {
            log.info("更新联系方式");
            //业务上必须有且仅有一个默认收款方式 如果本次提交的不是默认方式且不存在收款方式  则报错提示
            if (!isDefaultType && !existDefaultExcludeType(paymentInfos, paymentType)) {
                throw new BusinessException(ExceptionMsgEnum.DEFAULT_PAYMENT_TYPE_ERROR);
            }

            this.updateUserPayment(uid, savePaymentDTO, paymentInfo.getId());
        }

        //如果本次选择了设置为默认方式，把其他的收款方式置为非默认
        if (isDefaultType) {
            HeroUserPaymentInfo otherDefaultPaymentInfo = paymentInfos.stream()
                .filter(record -> !record.getPaymentType().equals(paymentType) &&
                    NumConsts.ONE.equals(record.getIsDefaultType()))
                .findFirst()
                .orElse(null);
            if (Objects.nonNull(otherDefaultPaymentInfo)) {
                log.info("将其他收款方式取消默认");
                this.cancelDefaultById(otherDefaultPaymentInfo.getId());
            }
        }
    }

    @Override
    public UserPaymentVO queryUserDefaultPaymentInfo(Long uid) {
        List<HeroUserPaymentInfo> paymentInfos = this.listByUid(uid);
        return paymentInfos.stream()
            .filter(record -> NumConsts.ONE.equals(record.getIsDefaultType()))
            .findFirst()
            .map(this::convertUserPaymentVO)
            .orElse(null);
    }

    @Override
    public List<HeroUserPaymentInfo> listByUid(Long uid) {
        if (Objects.isNull(uid)) {
            throw new IllegalArgumentException(ExceptionMsgEnum.PARAM_ERROR.getErrorMsg());
        }
        HeroUserPaymentInfo query = new HeroUserPaymentInfo();
        query.setUid(uid).setState(StateEnum.EFFECTIVE.getCode());

        return userPaymentInfoMapper.select(query);
    }

    @Override
    public HeroUserPaymentInfo getByUidAndType(Long uid, Integer paymentType) {
        if (Objects.isNull(uid) || Objects.isNull(paymentType)) {
            throw new IllegalArgumentException(ExceptionMsgEnum.PARAM_ERROR.getErrorMsg());
        }
        HeroUserPaymentInfo query = new HeroUserPaymentInfo();
        query.setUid(uid).setPaymentType(paymentType).setState(StateEnum.EFFECTIVE.getCode());

        return userPaymentInfoMapper.select(query).get(NumConsts.ZERO);
    }

    private UserPaymentVO convertUserPaymentVO(HeroUserPaymentInfo heroUserPaymentInfo) {
        if (heroUserPaymentInfo == null) {
            return null;
        }
        UserPaymentVO userPaymentVO = new UserPaymentVO();
        userPaymentVO.setPaymentType(heroUserPaymentInfo.getPaymentType());
        userPaymentVO.setPayeeName(heroUserPaymentInfo.getPayeeName());
        userPaymentVO.setPayCode(heroUserPaymentInfo.getPayCode());
        userPaymentVO.setIsDefaultType(heroUserPaymentInfo.getIsDefaultType());
        return userPaymentVO;
    }

    private void saveUserPayment(Long uid, SavePaymentDTO savePaymentDTO) {
        HeroUserPaymentInfo saveRecord = this.paymentDto2Po(savePaymentDTO);
        saveRecord.setUid(uid)
            .setState(StateEnum.EFFECTIVE.getCode())
            .setCreateBy(uid)
            .setUpdateBy(uid);
        userPaymentInfoMapper.insertSelective(saveRecord);
    }

    private void updateUserPayment(Long uid, SavePaymentDTO savePaymentDTO, Long updateId) {
        HeroUserPaymentInfo updateRecord = this.paymentDto2Po(savePaymentDTO);
        updateRecord.setId(updateId).setCreateBy(uid).setUpdateBy(uid);
        userPaymentInfoMapper.updateByPrimaryKey(updateRecord);
    }

    private HeroUserPaymentInfo paymentDto2Po(SavePaymentDTO savePaymentDTO) {
        HeroUserPaymentInfo userPaymentInfo = new HeroUserPaymentInfo();
        userPaymentInfo.setPaymentType(savePaymentDTO.getPaymentType())
            .setPayeeName(savePaymentDTO.getPayeeName())
            .setPayCode(savePaymentDTO.getPayCode())
            .setIsDefaultType(savePaymentDTO.getIsDefaultType());
        return userPaymentInfo;
    }

    private void cancelDefaultById(Long id) {
        HeroUserPaymentInfo updateRecord = new HeroUserPaymentInfo();
        updateRecord.setId(id).setIsDefaultType(NumConsts.ZERO);
        userPaymentInfoMapper.updateByPrimaryKey(updateRecord);
    }

    /**
     * 除了该方式外是否有默认收款方式
     *
     * @param paymentInfos
     * @param paymentType
     * @return boolean
     * @author  hanjunjun
     * @date 2024/7/29
     **/
    private boolean existDefaultExcludeType(List<HeroUserPaymentInfo> paymentInfos, Integer paymentType) {
        if (CollectionUtils.isEmpty(paymentInfos)) {
            return false;
        }
        Assert.notNull(paymentType);
        return paymentInfos.stream().anyMatch(paymentInfo ->
                !paymentType.equals(paymentInfo.getPaymentType()) && NumConsts.ONE.equals(paymentInfo.getIsDefaultType()));
    }
}
